package zarzadcyZdarzen;


import java.util.concurrent.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import gui.*;
import gameManager.*;
/**
 *
 * Klasa obsługująca kolejki zdarzeń, wrzuca komendy odpowiadające zdarzeniom od użytkownika
 * do kolejki komunikatów wychodzących i pobiera na bieżąco komendy przychodzące od serwera
 * następnie kieruje ich wykonanie do CommandExecutora. Klasa implementuje Runnable i 
 * jest wątkiem. Zakończenie wątku powoduje metoda set_koniec.
 * @author Konrad Sobczak
 * @author Kamil Nowak
 *
 *
 */

public class EventDispacher implements Runnable {
	private CommandExecutor executor;
	private BlockingQueue<String> in;
	private BlockingQueue<String> out;
	AtomicBoolean koniec=new AtomicBoolean();
	
	/**
	 * Tworzy obiekt EventDispachera
	 * @param in - kolejka komunikatów wejściowych
	 * @param out - kolejka komunikatów wyjściowych
	 * @param executor - CommandExecutor który będziemy wołali w przypadku wystąpienia
	 * w kolejce komunikatów wejściowych do ich wykonania
	 */
	public EventDispacher(BlockingQueue<String> in, BlockingQueue<String> out, CommandExecutor executor){
		this.in = in;
		this.out = out;
		this.executor = executor;
		koniec.set(true);
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komendę PROMOOK
	 * @param id_stolu - id stołu dla którego zachodzi to zdarzenie
	 */
	public void SendPromoOk(int id_stolu) {
		out.add("PROMOOK|" + id_stolu);
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat FINISHGAMEOK
	 * @param id_stolu - id stołu dla którego zachodzi to zdarzenie
	 */
	public void sendFinishOk(int id_stolu){
		out.add("FINISHGAMEOK|"+id_stolu);
	}
	
	/** 
	 * Wrzuca do kolejki wyjściowej komunikat FINISHGAME
	 * @param id_stolu - id stołu dla którego zaszło to zdarzenie
	 */
	public void sendFinishGame(int id_stolu){
		out.add("FINISHGAME|" + id_stolu + "|" + executor.get_MainWindow().get_id_user() + "|" + executor.get_MainWindow().get_imie() + "|1|wygralem");
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat MOVEOK
	 * @param id_stolu - id stołu dla którego zaszło to zdarzenie
	 */
	public void sendMoveOk(int id_stolu){
		out.add("MOVEOK|" + id_stolu);
	}
	
	/**
	 * Wrzuca do kolejki wejściowej komunikat PROMO
	 * @param id_stolu - id stołu dla którego nastąpiło to zdarzenie
	 * @param xp - początkowa pozycja promowanego pionka x
	 * @param yp - początkowa pozycja promowanego pionka y
	 * @param xk - końcowa pozycja promowanego pionka x
	 * @param yk - końcowa pozycja promowanego pionka y
	 * @param symbol - symbol figury na którą promowano pionka
	 */
	public void sendPromo(int id_stolu,int xp,int yp,int xk,int yk,int symbol){
		out.add("PROMO|" + id_stolu + "|" + executor.get_MainWindow().get_id_user() + "|" + executor.get_MainWindow().get_imie() + "|" + xp + "|" + yp +"|" +xk +"|" + yk + "|" + symbol);
		System.out.println("tu bylem");
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat MOVE
	 * @param id_stolu - id stołu dla, którego nastąpiło to zdarzenie 
	 * @param xp - początkowa pozycja poruszonej bierki x
	 * @param yp - początkowa pozycja poruszonej bierki y
	 * @param xk - końcowa pozycja poruszonej bierki x
	 * @param yk - końcowa pozycja poruszonej bierki y
	 */
	public void sendMove(int id_stolu,int xp,int yp,int xk,int yk){
		out.add("MOVE|" + id_stolu + "|" + executor.get_MainWindow().get_id_user() + "|" + executor.get_MainWindow().get_imie() + "|" + xp + "|" + yp +"|" +xk +"|" + yk);
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat LEAVETABLE
	 * @param id_stolu - id stołu dla którego nastąpiło to zdarzenie
	 */
	public void sendLeaveTable(int id_stolu){
		out.add("LEAVETABLE|" + id_stolu + "|" + executor.get_MainWindow().get_id_user() + "|" + executor.get_MainWindow().get_imie());
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat JOIN
	 * @param id_stolu - id stołu do którego chcemy dołączyć
	 * @param id_user - nasz id usera
	 * @param login - nasz login
	 */
	public void sentJoinMsg(int id_stolu,long id_user, String login){
		out.add("JOIN|" + id_stolu + "|" + id_user + "|" + login);
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat SMSG (send message - dla chatow)
	 * @param gdzie - 0 dla czatu ogólnego, id stołu dla czatów między dwoma graczami na stole
	 * @param co - treść komunikatu
	 */
	public void sendChatMsg(int gdzie,String co){
		out.add("SMSG|" + gdzie + "|" + executor.get_MainWindow().get_id_user()+"|" + executor.get_MainWindow().get_imie() + "|" + co);
	}
	
	
	public void sendChatMsg(int gdzie,long id_user,String kto,String co){
		out.add("SMSG|" + gdzie + "|" + id_user +"|" + kto + "|" + co);
	}
	
	/**
	 * Wrzuca do kolejki wyjściowej komunikat CREATETABLE
	 * @param id_user - id użytkownika który zakłada stół
	 * @param login - login użytkownika który zakłada stół
	 * @param tableName - nazwa zakładanego stołu
	 */
	public void sendCreateTable(long id_user,String login,String tableName){
		out.add("CREATE|" + id_user + "|" + login + "|" + tableName);
	}
	
	/**
	 * Wywołanie metody kończy wykonywanie wątku
	 *
	 */
	public void set_koniec(){
		koniec.set(false);
	}
	
	/**
	 * Pętla sprawdzająca warunek końca, pobierająca komunikaty z kolejki wejściowej 
	 * w przypadku gdy jest tam jakiś komunikat powoduje jego wykonanie, śpi 50ms
	 */
	public void run(){
		String command;
		out.add("GETTABLES");
		while(koniec.get()==true){
			try{
				if((command=in.poll())!=null){
					executor.parse_and_execute(command);
				}
				Thread.sleep(50);
			}
			catch(InterruptedException e){
			
			}
		}
	}

	
	
}
